package persistencia;

import java.util.Date;
import java.util.List;

import javax.persistence.Entity;

import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.MatchMode;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;

public class HibernateDAO{

	public HibernateDAO(){
	}

	public static void alterar(Persistente obj) throws ExcecaoDePersistencia {
		obj.validarSalvamento();
		HibernateUtil.getSessao().saveOrUpdate(obj);
	}

	public static void criar(Persistente obj) throws ExcecaoDePersistencia {
		obj.validarSalvamento();
		HibernateUtil.getSessao().save(obj);
	}

	public static void confirmarTransacao(){
		HibernateUtil.confirmarTransacao();
	}

	public static void cancelarTransacao(){
		HibernateUtil.cancelarTransacao();
	}

	public static void remover(Persistente obj) throws ExcecaoDePersistencia {
		obj.validarRemocao();
		HibernateUtil.getSessao().delete(obj);
	}

	@SuppressWarnings("unchecked")
	public static <T> T recuperarPorCampo(String campo, Object objeto, Class<T> classe){
		Criteria c = HibernateUtil.getSessao().createCriteria(classe)
		  .add(Restrictions.eq(campo, objeto));
		return (T) c.uniqueResult();
	}

	@SuppressWarnings("unchecked")
	public static List recuperarPorCampo2(String campo, Object objeto, Class classe){
		Criteria c = HibernateUtil.getSessao().createCriteria(classe)
		  .add(Restrictions.eq(campo, objeto));
		return c.list();
	}

	@SuppressWarnings("unchecked")
	public static List recuperarPorCampoLike(String campo, String expressao, Class classe)
			throws ExcecaoDePersistencia {
		Criteria c = HibernateUtil.getSessao().createCriteria(classe)
		  .add(Restrictions.like(campo, expressao, MatchMode.ANYWHERE));
		return c.list();
	}

	public static <T> T recuperarPorId(String id, Class<T> classe) throws ExcecaoDePersistencia {
		return recuperarPorCampo("id", id, classe);
	}

	public static List recuperarTodos(String ordem, Class classe) throws ExcecaoDePersistencia {
		Criteria c = HibernateUtil.getSessao().createCriteria(classe);
		c.addOrder(Order.asc(ordem));
		return c.list();
	}

	public static List recuperarPorPeriodo(String campo, Date dataInicial,
			Date dataFinal, Class classe) throws Exception {
		Criteria c = HibernateUtil.getSessao().createCriteria(classe).add(
				Restrictions.between(campo, dataInicial, dataFinal));
		return c.list();
	}

	public static List recuperarPorCampos(String[] nomeDasChaves, Object[] chaves, String campoDeOrdenacao, Class classe){
	  StringBuffer hql = new StringBuffer();
	  hql.append("from ")
	  	 .append(classe.getName())
	  	 .append(" where ")
	  	 .append(" ( ");
	  	 for (int i = 0; i < nomeDasChaves.length; i++) {
 			hql.append(nomeDasChaves[i])
  				.append(" = ")
  				.append("?");
			if ( i != nomeDasChaves.length -1){
				hql.append(" and ");
			}
		}
	  	hql.append(" ) ");
	  	hql.append(" order by ")
	  		.append(campoDeOrdenacao)
	  		.append(" asc ");
	  	Query q = HibernateUtil.getSessao().createQuery(hql.toString());
	  	for (int i = 0; i < nomeDasChaves.length; i++) {
	  		if (chaves[i] instanceof Persistente) {
		  	  q.setString(i, ((Persistente)chaves[i]).getId().toString());
			} else {
	  		  q.setString(i, chaves[i].toString());
			}
		}
	  	List result = q.list();
	  	System.out.println(hql);
  	    return result;
	  }
	}
